package nsenter

/*
#define _GNU_SOURCE
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

__attribute__((constructor)) void enter_namespace(void) {
    // 这里的代码会在 Go 运行是启动前执行，它会在单线程的 C 上下文中运行
	// 为了避免执行其他命令的时候这段 setns 的逻辑影响到其他功能，
	// 因此，在这段代码前面一开始的位置就添加了环境变量检测，没有对应的环境变量时，就直接退出
	// 对于不使用 exec 功能的 Go 代码，只要不设置对应的环境变量，这段 C 代码就不会运行，这样就不会影响原来的逻辑。
    char *my_docker_pid;
    my_docker_pid = getenv("my_docker_pid");
    if (my_docker_pid) {
        fprintf(stdout, "got my_docker_pid=%S\n",my_docker_pid);
    } else {
        fprintf(stdout, "missing my_docker_pid env skip nsenter");
        // 如果没有指定 PID 就不需要继续执行，直接退出
        return;
    }
    char *my_docker_cmd;
    my_docker_cmd = getenv("my_docker_cmd");
    if (my_docker_cmd) {
        fprintf(stdout, "got my_docker_cmd=%S\n",my_docker_cmd);
    } else {
        fprintf(stdout, "missing my_docker_cmd env skip nsenter");
        // 如果没有指定命令就不需要继续执行，直接退出
        return;
    }
    int i;
    char nsPath[1024];
    // 需要进入的 5 中 Namespace
    char *namespaces[] = {"ipc", "uts", "net", "pid", "mnt"};

    for (i=0; i<5; i++) {
        // 拼接对应路径，类似于 /proc/pid/ns/ipc 这样
        sprintf(nsPath, "/proc/%s/ns/%s", my_docker_pid, namespaces[i]);
        int fd = open(nsPath, O_RDONLY);
        // 执行 setns 系统调用，进入对应的 namespace
        if (setns(fd, 0) == -1) {
            fprintf(stderr, "setns on %s namespace failed: %s\n", namespaces[i], strerror(errno));
        } else {
            fprintf(stdout, "setns on %s namespace succeeded\n", namespaces[i]);
        }
        close(fd);
    }
    // 在进入的 Namespace 中执行指定命令，然后退出
    int res = system(my_docker_cmd);
    exit(0);
    return;
}
*/
import "C"
